package com;


import com.entity.CssItem;
import com.entity.ReadPDFEntity;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.*;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;


public class Test1 {
    private static final Logger logger = LoggerFactory.getLogger(ReadPDFUtil.class);
    private static Shell shell = null;
    private static final String type = ".pdf";
    private static final Integer LEN = 1;

    private static final Integer DEFAULT_VAL = 1;

    private static String html = "";

    private static Elements es;
    private static Document document;

    private static Text text;

    private static final String[] colors = {"input", "text"};


    public static void main(String[] args) {
        Display display = new Display();
        shell = new Shell(display);
        shell.setText("SWT Browser Test");
        shell.setSize(1000, 1400);

        text = new Text(shell, SWT.BORDER);
        text.setEnabled(Boolean.FALSE);
        text.setBounds(110, 5, 560, 40);
        Button button = new Button(shell, SWT.BORDER);
        button.setBounds(680, 5, 100, 40);
        button.setText("选择");

        Label label = new Label(shell, SWT.LEFT);
        label.setText("请选择 :");
        label.setBounds(5, 5, 100, 40);

        Browser browser = createBrowser(shell);

        button.addListener(SWT.Selection, new Listener() {
            public void handleEvent(Event event) {
                btnClick(browser);
                //btnClickThread(display,browser);
            }
        });


        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        display.dispose();

    }

    private static Browser createBrowser(Shell shell) {
        Browser browser = new Browser(shell, SWT.FILL);
        sizeFunc(shell, browser);
        return browser;
    }

    private static void sizeFunc(Shell shell, final Browser browser) {
        shell.addPaintListener(new PaintListener() {

            @Override
            public void paintControl(org.eclipse.swt.events.PaintEvent e) {
                browser.setBounds(5, 45, e.width - 20, e.height - 20);
            }
        });
    }


    private static void btnClickThread(Display display, final Browser browser) {
        if (display.isDisposed()) {
            Runnable runnable = new Runnable() {
                public void run() {
                    btnClick(browser);
                }
            };
            display.syncExec(runnable);
        }

    }


    private static void btnClick(Browser browser) {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setPreferredSize(new Dimension(600, 600));
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);

        fileChooser.setFileFilter(new FileFilter() {

            @Override
            public String getDescription() {
                // TODO Auto-generated method stub
                return "PDF文件(*" + type + ")";
            }

            @Override
            public boolean accept(File f) {
                if (StringUtils.indexOf(f.getName(), ".") == -1) {
                    return true;
                }
                return StringUtils.endsWithIgnoreCase(f.getName(), type);
            }
        });
        int result = fileChooser.showDialog(null, "选择文件");
        if (result == JFileChooser.APPROVE_OPTION) {
            String path = fileChooser.getSelectedFile().getAbsolutePath();
            text.setText(path);
            ReadPDFEntity entity = ReadPDFUtil.readPDF(path);
            browser.setUrl(entity.getPath());
            logger.debug("[{}]", entity.getPath());
//            browser.setText(html,false);
            readAloud(entity.getHtml(), browser);
//            oclick(browser);
        }

    }

    private static void oclick(Browser browser) {
//        new Thread(new Runnable() {
//
//            @Override
//            public void run() {
//                    browser.getDisplay().asyncExec(new Runnable() {
//                        @Override
//                        public void run() {
//                            while (true){
//                                Date date = new Date();
//                                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//                                browser.setText(simpleDateFormat.format(date));
//
//                                sleepFun();
//                            }
//                        }
//                    });
//            }
//        }).start();


        new Thread(new Runnable() {

            @Override
            public void run() {
                while (true) {
                    Display.getDefault().asyncExec(new Runnable() {
                        @Override
                        public void run() {
                            Date date = new Date();
                            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            browser.setText(simpleDateFormat.format(date));
                        }
                    });
                    sleepFun();
                }
            }
        }).start();

    }

    private static void btnClick(Browser browser, Display display) {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fileChooser.setFileFilter(new FileFilter() {

            @Override
            public String getDescription() {
                // TODO Auto-generated method stub
                return "PDF文件(*" + type + ")";
            }

            @Override
            public boolean accept(File f) {
                if (StringUtils.indexOf(f.getName(), ".") == -1) {
                    return true;
                }
                return StringUtils.endsWithIgnoreCase(f.getName(), type);
            }
        });
        int result = fileChooser.showDialog(null, "选择文件");
        if (result == JFileChooser.APPROVE_OPTION) {
//            String htmlString = ReadPDFUtil.readPDF(fileChooser.getSelectedFile().getAbsolutePath());
//            browser.setText(htmlString, false);

        }

    }


    private static void readAloud(String html, Browser browser) {
        Document document = Jsoup.parse(html);
        if (Objects.isNull(document)) {
            return;
        }
        Elements es = document.getAllElements();
        if (CollectionUtils.isEmpty(es)) {
            return;
        }

        int size = CollectionUtils.size(es);

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < size; i++) {
                    String txt = readAloud(es, i);
                    if (StringUtils.isNotEmpty(txt)) {
                        sleepFun();

                        String path = ReadPDFUtil.writeFile(document.html()) + "?time=" + System.currentTimeMillis();
                        logger.debug("[{}]", path);
                        String path1 = "E:\\3\\7\\" + i + ".html";
                        ReadPDFUtil.writeFile(document.html(), path1);
                        try {
                            browser.getDisplay().asyncExec(new Runnable() {
                                @Override
                                public void run() {
//                                browser.setUrl(path1);
                                    browser.setText(document.html(), false);
                                }
                            });
                        } catch (Exception e) {
                            logger.debug(e.getMessage());
                        }


//                    Display.getDefault().asyncExec(new Runnable() {
//                        @Override
//                        public void run() {
//                            browser.setUrl(path1);
//                           // browser.refresh();
//
//                           // Date date = new Date();
//                           // SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//                            //browser.setText(simpleDateFormat.format(date));
//                        }
//                    });
                        boolean flag = ReadUtil.speeckMsg(txt);
                        if (Objects.equals(Boolean.FALSE, flag)) {
                            logger.error("[{}]", "朗读失败");
                        }
                        logger.debug("[{}]", txt);

                    }

                }
            }
        }).start();

//        do {
//            readAloud(es, document, browser, atomic);
//        } while (atomic.get() <= size);
    }

//    private static void readAloud(String html, Browser browser) {
//        Document document = Jsoup.parse(html);
//        if (Objects.isNull(document)) {
//            return;
//        }
//        Elements es = document.getAllElements();
//        if (CollectionUtils.isEmpty(es)) {
//            return;
//        }
////        java.util.List<Element> esList = es.stream().filter(e -> StringUtils.isNotEmpty(e.text())).collect(Collectors.toList());
////
//        AtomicInteger atomic = new AtomicInteger(DEFAULT_VAL);
//        //int size = 10000;
////        int size = StringUtils.length(html);
////        int size = CollectionUtils.size(esList);
//        int size = CollectionUtils.size(es);
////        if (size == 0) {
////            return;
////        }
//        AtomicInteger flagAto = new AtomicInteger(0);
//        new Thread(new Runnable() {
//
//            @Override
//            public void run() {
//                while (true) {
//                   StringBuilder builder = new StringBuilder();
//                    Display.getDefault().asyncExec(new Runnable() {
//                        @Override
//                        public void run() {
//
////                            String html = readAloud(es, document, browser, atomic);
////                            if(StringUtils.isNotEmpty(html)){
////                                browser.setText(html);
////
////                            }
//                            String txt = readAloud(es, atomic);
//                            if (StringUtils.isNotEmpty(txt)) {
//                                browser.setText(document.html(), true);
//
//                                try {
//                                    FileUtils.write(new File("E:\\3\\7\\" + atomic.get() + ".html"), document.html());
//                                    flagAto.getAndAdd(1);
//                                } catch (IOException e) {
//                                    throw new RuntimeException(e);
//                                }
//                                builder.append(txt);
//                            } else {
//                                flagAto.set(0);
//                            }
//                        }
//                    });
//                    if (atomic.get() > size) {
//                        break;
//                    }
//                    if(StringUtils.isNotEmpty(builder.toString())) {
//                        ReadUtil.freeTTS(builder.toString());
//                       // sleepFun();
//                    }
//                }
//            }
//        }).start();
////        do {
////            readAloud(es, document, browser, atomic);
////        } while (atomic.get() <= size);
//    }

//    private static String readAloud(Elements es, Document document, AtomicInteger atomic) {
//        int index = atomic.getAndAdd(1);
//        Element element = es.get(index);
//
//        if (Objects.isNull(element)) {
//            return null;
//        }
//
//        Elements children = element.children();
//        String txt = StringUtils.trim(element.text());
//        int size = CollectionUtils.isEmpty(children) ? 0 : CollectionUtils.size(children);
//
//        if (size == 0 && isIgnorColor(element.tagName())) {
//            String style = element.attr("style");
//            if (Objects.isNull(style)) {
//                style = "";
//            }
//            style = style + ";color:red;fill:red;";
//            element.attr("style", style);
//
//            logger.debug("[{}]", txt);
//            return document.html();
//        }
//
//        return null;
//    }

//    private static String readAloud(Elements es, Document document, AtomicInteger atomic) {
//        int index = atomic.getAndAdd(1);
//        Element element = es.get(index);
//
//        if (Objects.isNull(element)) {
//            return null;
//        }
//
//        if (index > 1) {
//            readAloud(es, index - 1, Boolean.FALSE);
//        }
//        boolean flag = readAloud(es, index, Boolean.TRUE);
//
//        return flag ? document.html() : null;
//    }

    private static String readAloud(java.util.List<Element> es, int index) {
        Element element = es.get(index);

        if (Objects.isNull(element)) {
            return null;
        }

        if (index > 0) {
            readAloud(es, index - 1, Boolean.FALSE);
        }
        return readAloud(es, index, Boolean.TRUE);
    }
//    private static String readAloud(java.util.List<Element> es, AtomicInteger atomic) {
//        int index = atomic.getAndAdd(1);
//        Element element = es.get(index);
//
//        if (Objects.isNull(element)) {
//            return null;
//        }
//
//        if (index > 1) {
//            readAloud(es, index - 1, Boolean.FALSE);
//        }
//        return readAloud(es, index, Boolean.TRUE);
//    }


    private static String readAloud(java.util.List<Element> es, int index, boolean flag) {
        Element element = es.get(index);

        if (Objects.isNull(element)) {
            return null;
        }

        Elements children = element.children();
        String txt = StringUtils.trim(element.text());

        if (StringUtils.isNotEmpty(txt)) {
            int size = CollectionUtils.isEmpty(children) ? 0 : CollectionUtils.size(children);

            if (size == 0 && isIgnorColor(element.tagName())) {
                String style = element.attr("style");
                List<CssItem> cssItems = switchCss(style);
                if (CollectionUtils.isEmpty(cssItems)) {
                    cssItems.add(new CssItem("color", "red"));
                    cssItems.add(new CssItem("fill", "red"));
                    cssItems.add(new CssItem("background-color", "#F5deb3"));
                } else {
                    addOrRemoveColor(cssItems, "color", "red", flag);
                    addOrRemoveColor(cssItems, "fill", "red", flag);
                    addOrRemoveColor(cssItems, "background-color", "#F5deb3", flag);
                }

                element.attr("style", combCss(cssItems));
                return txt;
            }
        }
        return null;
    }

    private static void addOrRemoveColor(List<CssItem> cssItems, String key, String color, boolean flag) {
        Optional<CssItem> optional = cssItems.stream().filter(c -> StringUtils.equals(c.getItem(), key)).findFirst();
        if (flag) {
            if (optional.isPresent()) {
                if (CollectionUtils.isNotEmpty(optional.get().getValues())) {
                    Set<String> colors = new LinkedHashSet<>();
                    colors.addAll(optional.get().getValues());
                    cssItems.add(new CssItem("old-" + key, colors));
                    optional.get().getValues().clear();
                }
                optional.get().getValues().add(color);
            } else {
                cssItems.add(new CssItem(key, color));
            }
        } else {
            String oldKey = "old-" + key;
            Optional<CssItem> optional1 = cssItems.stream().filter(c -> StringUtils.equals(c.getItem(), oldKey)).findFirst();
            if (optional1.isPresent()) {
                if (CollectionUtils.isNotEmpty(optional.get().getValues())) {
                    optional.get().getValues().clear();
                    Set<String> colors = new LinkedHashSet<>();
                    colors.addAll(optional.get().getValues());
                    optional.get().setValues(colors);
                }
            } else {
                cssItems.remove(optional.get());
            }
        }
    }


//    private static boolean readAloud(Elements es, int index, boolean flag) {
//        Element element = es.get(index);
//
//        if (Objects.isNull(element)) {
//            return false;
//        }
//
//        Elements children = element.children();
//        String txt = StringUtils.trim(element.text());
//        if (StringUtils.isNotEmpty(txt)) {
//            int size = CollectionUtils.isEmpty(children) ? 0 : CollectionUtils.size(children);
//
//            if (size == 0 && isIgnorColor(element.tagName())) {
//                String style = element.attr("style");
//                List<CssItem> cssItems = switchCss(style);
//                if (CollectionUtils.isEmpty(cssItems)) {
//                    cssItems.add(new CssItem("color", "red"));
//                    cssItems.add(new CssItem("fill", "red"));
//                } else {
//                    Optional<CssItem> optional = cssItems.stream().filter(c -> StringUtils.equals(c.getItem(), "color")).findFirst();
//                    if (flag) {
//                        if (optional.isPresent()) {
//                            optional.get().getValues().add("red");
//                        } else {
//                            cssItems.add(new CssItem("color", "red"));
//                        }
//                    } else {
//                        optional.get().getValues().remove("red");
//                    }
//
//
//                    optional = cssItems.stream().filter(c -> StringUtils.equals(c.getItem(), "fill")).findFirst();
//                    if (flag) {
//                        if (optional.isPresent()) {
//                            optional.get().getValues().add("red");
//                        } else {
//                            cssItems.add(new CssItem("color", "red"));
//                        }
//                    } else {
//                        optional.get().getValues().remove("red");
//                    }
//
//                }
//
//
//                element.attr("style", combCss(cssItems));
//
//                logger.debug("[{}]", txt);
//                return Boolean.TRUE;
//            }
//        }
//        return Boolean.FALSE;
//    }

    private static String combCss(List<CssItem> cssItems) {
        if (CollectionUtils.isEmpty(cssItems)) {
            return "";
        }
        StringBuilder builder = new StringBuilder();

        for (CssItem cssItem : cssItems) {
            if (CollectionUtils.isNotEmpty(cssItem.getValues())) {
                builder.append(cssItem.getItem());
                builder.append(":");

                StringBuilder cssVal = new StringBuilder();
                for (String value : cssItem.getValues()) {
                    cssVal.append(value);
                    cssVal.append(" ");
                }

                builder.append(cssVal);
                builder.append(";");
            }
        }
        return builder.toString();
    }

    private static java.util.List<CssItem> switchCss(String style) {
        if (StringUtils.isEmpty(style)) {
            return Collections.emptyList();
        }
        String[] styles = StringUtils.split(style, ";");


        int length = ArrayUtils.getLength(styles);
        if (0 == length) {
            return Collections.emptyList();
        }

        return Arrays.stream(styles).map(s -> {
            if (StringUtils.isEmpty(StringUtils.trim(s))) {
                return null;
            }
            String[] cs = StringUtils.split(s, ":");
            int len = ArrayUtils.getLength(cs);
            if (len > 1) {
                Set<String> vals = new LinkedHashSet<>();
                String[] values = StringUtils.split(cs[1], " ");
                len = ArrayUtils.getLength(values);
                for (int i = 0; i < len; i++) {
                    String csVal = StringUtils.trim(values[i]);
                    if (StringUtils.isNotEmpty(csVal)) {
                        vals.add(csVal);
                    }
                }
                return new CssItem(StringUtils.trim(cs[0]), vals);
            }
            return null;
        }).filter(obj -> Objects.nonNull(obj)).collect(Collectors.toList());
    }

    private static boolean isIgnorColor(String tagName) {
        for (String sourTagName : colors) {
            if (StringUtils.equalsIgnoreCase(sourTagName, tagName)) {
                return true;
            }
        }
        return false;
    }

    private static void sleepFun() {
        try {
            for (int i = 0; i < 2; i++) {
                Thread.sleep(1000);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

//	private static void readAloud(Document document,Browser browser) {
//		Elements elements = document.children();
//		if(CollectionUtils.isNotEmpty(elements)) {
//			elements.forEach(el->{
//				readChild(el,browser,document);
//			});
//		}
//	}

//	private static void readChild(Element el,Browser browser,Document document) {
//		if(Objects.nonNull(el)) {
//			Elements es = el.children();
//			if(CollectionUtils.isNotEmpty(es)) {
//				es.forEach(childEL->{
//					readChild(childEL,browser,document);
//				});
//			}else {
//				String text = el.text();
//				boolean flag = true;
//				for (String tagName : colors) {
//					if(StringUtils.equalsIgnoreCase(el.tagName(), tagName)) {
//						String style = el .attr("style");
//						if(Objects.isNull(style)) {
//							style = "";
//						}
//						style = style+";color:red";
//						el.attr("style", style);
//						
//						flag = false;
//						break;
//					}
//				}
//				
//				if(flag && StringUtils.isNotEmpty(StringUtils.trim(text))) {
//					el.append("<dd style='color:red'>"+text+"</dd>");
//				}
//				
//				browser.setText(document.html(), false);
//				try {
//					Thread.sleep(1000);
//				} catch (InterruptedException e) {
//					// TODO Auto-generated catch block
//					e.printStackTrace();
//				}
//			}
//		}
//	}


//	private static void readAloud(String html,Browser browser) {
//		new Thread(new Runnable() {
//
//			@Override
//			public void run() {
//				int length = StringUtils.length(html);
//				Document document = Jsoup.parse(html);
//				String text = document.text();
//				int index = 0;
//				for (int i = 0; i < length; i++) {
//					int len = length-i> LEN?LEN:length-i;
//					String cha = StringUtils.substring(text, i,i+len);
//					if(StringUtils.isNotEmpty(StringUtils.trim(cha))) {
//					
//						int index1 = StringUtils.indexOf(html, cha,index);
//						
//						String html1 = StringUtils.substring(html, index1,index1+1);
//						String html2 = StringUtils.substring(html, 0,index1);
//						String html3 = StringUtils.substring(html, index1+1);
//						
//						String html4 = html2+"<cccc color='red'>"+cha+"</cccc>"+html3;
//						Integer index12Integer = i;
//						Display.getDefault().asyncExec(new Runnable() {
//	
//							@Override
//							public void run() {
//								browser.setText(html4,false);
//								try {
//									FileUtils.write(new File("E:\\3\\7\\"+index12Integer+".html"), html4,"UTF-8");
//								} catch (IOException e) {
//									// TODO Auto-generated catch block
//									e.printStackTrace();
//								}
//							}});
//					
//						  try {
//							Thread.sleep(1000);
//						} catch (InterruptedException e) {
//							// TODO Auto-generated catch block
//							e.printStackTrace();
//						}
//					}
//					
//					logger.debug("[{}]",cha);
//				}
//			}
//			
//		}).start();

}
